﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlServerCe;
using System.Text;

namespace SqlCeDataAccess
{
  public class Parameters : IEnumerable<SqlCeParameter>, IDisposable
  {
    private List<SqlCeParameter> _parameters = new List<SqlCeParameter>();

    public SqlCeParameter this[int index]
    {
      get
      {
        return this._parameters[index];
      }
      set
      {
        if (index >= this._parameters.Count)
          throw new IndexOutOfRangeException();
        this._parameters[index] = value;
      }
    }

    /// <summary>
    /// Returns the number of parameters in the list.
    /// 
    /// </summary>
    public int Count
    {
      get
      {
        return this._parameters.Count;
      }
    }

    public Parameters()
    {
    }

    public Parameters(string parameterName, object value)
    {
      this.Add(parameterName, value);
    }

    /// <summary>
    /// Finds a parameter matching the provided name.
    /// 
    /// </summary>
    /// <param name="parameterName">Name of the parameter to find.</param>
    /// <returns>
    /// If found, returns the value of the index (positive integer). Otherwise, -1 is returned.
    /// </returns>
    public int FindParameter(string parameterName)
    {
      for (int index = 0; index < this._parameters.Count; ++index)
      {
        if (this._parameters[index].ParameterName == parameterName)
          return index;
      }
      return -1;
    }

    /// <summary>
    /// Finds a parameter matching the provided name.
    /// 
    /// </summary>
    /// <param name="xmlRootName">root name item</param><param name="item">identity of item</param><param name="values">List of string values</param>
    /// <returns>
    /// Returns a string in XML format to utilize in SQL.
    /// </returns>
    public static string BuildXmlString(string xmlRootName, string item, List<string> values)
    {
      StringBuilder stringBuilder = new StringBuilder();
      stringBuilder.AppendFormat("<{0}>", (object)xmlRootName);
      for (int index = 0; index < values.Count; ++index)
        stringBuilder.AppendFormat("<" + item + ">{0}</" + item + ">", (object)values[index]);
      stringBuilder.AppendFormat("</{0}>", (object)xmlRootName);
      return ((object)stringBuilder).ToString();
    }

    /// <summary>
    /// Adds the given parameter to the list of parameters
    /// 
    /// </summary>
    /// <param name="parameter">Parameter to add</param>
    /// <returns>
    /// True if the parameter was added. False if a parameter with the same name already
    ///             existed in the parameter list
    /// </returns>
    public bool Add(SqlCeParameter parameter)
    {
      if (this.FindParameter(parameter.ParameterName) > 0)
        return false;
      this._parameters.Add(parameter);
      return true;
    }

    /// <summary>
    /// Creates a new parameter with the given name and value and adds it to
    ///             the list of parameters.
    /// 
    /// </summary>
    /// <param name="parameterName">Name of the parameter</param><param name="value">Value of the parameter</param>
    /// <returns>
    /// True if the parameter was added. False if a parameter with the same name already
    ///             existed in the parameter list
    /// </returns>
    public bool Add(string parameterName, object value)
    {
      if (this.FindParameter(parameterName) > 0)
        return false;
      this._parameters.Add(new SqlCeParameter(parameterName, value));
      return true;
    }

    /// <summary>
    /// Creates a new parameter with the given name, database type, and value
    ///             and adds it to the list of parameters.
    /// 
    /// </summary>
    /// <param name="parameterName">Name of the parameter</param><param name="type">Type of the parameter</param><param name="value">Value of the parameter</param>
    /// <returns>
    /// True if the parameter was added. False if a parameter with the same name already
    ///             existed in the parameter list
    /// </returns>
    public bool Add(string parameterName, DbType type, object value)
    {
      if (this.FindParameter(parameterName) > 0)
        return false;

      var sqlParameter = new SqlCeParameter(parameterName, value) {DbType = type};

      this._parameters.Add(sqlParameter);
      return true;
    }

    /// <summary>
    /// Removes a parameter with the provided name from the parameter list.
    /// 
    /// </summary>
    /// <param name="parameterName">Name of the parameter to remove.</param>
    /// <returns>
    /// True if the parameter was found and removed. Otherwise, returns false.
    /// </returns>
    public bool Remove(string parameterName)
    {
      int parameter = this.FindParameter(parameterName);
      if (parameter <= -1)
        return false;
      this._parameters.RemoveAt(parameter);
      return true;
    }

    /// <summary>
    /// Removes the parameter at the provided index.
    /// 
    /// </summary>
    /// <param name="index">Index of the parameter to remove</param>
    public void RemoveAt(int index)
    {
      this._parameters.RemoveAt(index);
    }

    /// <summary>
    /// Clear all parameters from the parameter list.
    /// 
    /// </summary>
    public void Clear()
    {
      this._parameters.Clear();
    }

    public IEnumerator<SqlCeParameter> GetEnumerator()
    {
      return this._parameters.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
      return this._parameters.GetEnumerator();
    }

    public void Dispose()
    {
      _parameters = null;
    }
  }
}
